This disclosure relates generally to the field of graphics processing. More particularly, this disclosure relates to techniques for identifying and generating optimized shader programs for executing applications.
In computer graphics, it is common to represent objects as triangulated polygons (i.e., triangles). The vertices of triangles may be associated not only with position (i.e., where in/on an object the vertex resides), but also with other attributes that may be used to properly render the triangle to which the vertex is a part. Such attributes may include color at the vertex point, reflectance of the surface at the vertex, textures of the surface at the vertex, and the normal of an approximated curved surface at the location of the vertex. In practice, a vertex may be thought of as a data structure that describes a point in two-dimensional (2D) or three-dimensional (3D) space. A collection of vertices (representing triangles), and information about their interconnectivity, may be used to model objects.
Modern graphics processing units (GPUs) have generalized architectures that permit customized programming through the use of “shader” programs. A shader program is a set of instructions that may be used to calculate rendering effects. In general, there are two principal types of shader programs: vertex shader programs and fragment shader programs. Vertex shader programs are run once for each vertex in a model and are responsible for how the vertex will be displayed. Fragment shader programs are run once for every pixel in every triangle in a model/object and are responsible for how individual pixels will be displayed. Vertex shader programs can manipulate properties such as the position, color, texture coordinates, and lighting characteristics of a vertex. Fragment shader programs can manipulate various attributes of individual pixels such as color and translucency characteristics. Fragment shaders may also be used to apply lighting values, shadows and specular highlights to a displayed object.
For model data to faithfully represent an object, often many thousands of vertices are required. To produce animation it may be desirable to have rendering rates of 60 frames per second (FPS). Consider then a model that has 100,000 vertices. If the desired drawing rate for the object represented by the model is 60 FPS, a vertex shader program would need to be executed six million (6,000,000) times per second.
Modern framebuffers (to which GPUs write their output), are composed of millions of elements (each element representing a pixel). Often each final frame of GPU rendering will be the result of compositing multiple fragments (i.e., pixels) with a blending operation between them. Consider then a framebuffer that is 2,000-by-1,000 elements in size. If each pixel is drawn twice (once to render the pixel and another to perform a blending operation), a fragment shader program would need to be executed four million (4,000,000) times per second for each frame. At a rendering rate of 60 FPS, the fragment shader program would need to be executed two hundred forty million (240,000,000) times per second.
Because of the extremely high number of executions for both vertex and fragment shaders during object rendering operations, it is important to be able to use optimized shader programs. Unlike programs written for general purpose central processing units (CPUs), generalized logic that employs conditional instructions for potentially unused instructions is not acceptable (such instructions take to much time to evaluate at the rates presented above). Thus, it would be beneficial to provide a technique to generate optimized shaders for an executing application at run-time.